#region Using Statements
using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;
#endregion

namespace KLib.Input
{
    public enum MouseButtons
    {
        Left,
        Right,
        Middle,
        M4,
        M5,
    }

    public class Mouse
    {
        #if !XBOX
        #region Fields
        private MouseState state;
        private MouseState prvState;

        private Vector2 position = Vector2.Zero;
        private Vector2 changeInPosition = Vector2.Zero;
        private Vector2 clickPosition = Vector2.Zero;
        private Vector2 distanceFromClick = Vector2.Zero;
        #endregion

        #region Properties
        #region States
        public MouseState State
        {
            get { return state; }
        }

        public MouseState PreviousState
        {
            get { return prvState; }
        }
        #endregion

        #region Positioning
        public Vector2 Position
        {
            get { return position; }
        }

        public Vector2 ChangeInPosition
        {
            get { return changeInPosition; }
        }

        public Vector2 ClickPosition
        {
            get { return clickPosition; }
        }

        public Vector2 DistanceFromClick
        {
            get { return distanceFromClick; }
        }
        #endregion

        public Vector2 MovementDirection
        {
            get 
            {
                Vector2 direction = Vector2.Zero;
                direction.X = position.X - clickPosition.X;
                direction.Y = position.Y - clickPosition.Y;
                direction.Normalize();
                return direction;
            }
        }

        #endregion

        #region Initialization

        public Mouse()
        {

        }

        #endregion

        #region Events
        public event EventHandler Click;
        #endregion

        #region Methods
        public void Update(GameTime gameTime)
        {
            prvState = state;
            state = Microsoft.Xna.Framework.Input.Mouse.GetState();

            position.X = state.X;
            position.Y = state.Y;

            changeInPosition.X = state.X - prvState.X;
            changeInPosition.Y = state.Y - prvState.Y;
            if (prvState.LeftButton == ButtonState.Released
                && state.LeftButton == ButtonState.Pressed)
            {
                clickPosition.X = state.X;
                clickPosition.Y = state.Y;

                if (Click != null)
                    Click(this, null);
            }
            else if (state.LeftButton == ButtonState.Pressed)
            {
                distanceFromClick = clickPosition - position;
            }
        }

        public bool IsButtonPressed(MouseButtons button)
        {
            switch (button)
            {
                case MouseButtons.Left:
                    return state.LeftButton == ButtonState.Pressed
                        && prvState.LeftButton == ButtonState.Released;
                case MouseButtons.Right:
                    return state.RightButton == ButtonState.Pressed
                        && prvState.RightButton == ButtonState.Released;
                case MouseButtons.Middle:
                    return state.MiddleButton == ButtonState.Pressed
                        && prvState.MiddleButton == ButtonState.Released;
                case MouseButtons.M4:
                    return state.XButton1 == ButtonState.Pressed
                        && prvState.XButton1 == ButtonState.Released;
                case MouseButtons.M5:
                    return state.XButton2 == ButtonState.Pressed
                        && prvState.XButton2 == ButtonState.Released;
            }
            return false;
        }

        public bool IsButtonDown(MouseButtons button)
        {
            switch (button)
            {
                case MouseButtons.Left:
                    return state.LeftButton == ButtonState.Pressed;
                case MouseButtons.Right:
                    return state.RightButton == ButtonState.Pressed;
                case MouseButtons.Middle:
                    return state.MiddleButton == ButtonState.Pressed;
                case MouseButtons.M4:
                    return state.XButton1 == ButtonState.Pressed;
                case MouseButtons.M5:
                    return state.XButton2 == ButtonState.Pressed;
            }
            return false;
        }

        public int GetScrollWheelChange()
        {
            return state.ScrollWheelValue - prvState.ScrollWheelValue;
        }
        #endregion
#endif
    }
}